package com.gky.gkytemplate.utils;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Value;

import java.io.*;
import java.util.Properties;


@Slf4j
public class SftpUtils {
    private static String sftpHost;
    private static Integer sftpPort;
    private static String sftpUserName;
    private static String sftpPassword;



    //主机
    @Value("${sftp.host}")
    public  void setSftpHost(String host) {
        SftpUtils.sftpHost = host;
    }
    //端口
    @Value("${sftp.port}")
    public  void setSftpPort(Integer port) {
        SftpUtils.sftpPort = port;
    }
    //用户
    @Value("${sftp.username}")
    public  void setSftpUserName(String username) {
        SftpUtils.sftpUserName = username;
    }
    //密码
    @Value("${sftp.password}")
    public  void setSftpPassword(String password) {
        SftpUtils.sftpPassword = password;
    }

    /**
     * 获取sftp链接 返回通信通道
     * @param sftpHost
     * @param sftpPort
     * @param sftpUserName
     * @param sftpPassword
     * @return
     */
    public static ChannelSftp getSftpChannel(String sftpHost, Integer sftpPort, String sftpUserName, String sftpPassword){
        Session session;
        Channel channel = null;
        JSch jSch = new JSch();
        try {
            session = jSch.getSession(sftpUserName,sftpHost,sftpPort);
            session.setPassword(sftpPassword);
            //配置链接的属性
            Properties properties = new Properties();
            properties.setProperty("StrictHostKeyChecking","no");
            session.setConfig(properties);
            //进行sftp链接
            session.connect();

            //获取通信通道
            channel = session.openChannel("sftp");
            channel.connect();

        } catch (JSchException e){
            e.printStackTrace();
        }

        return (ChannelSftp)channel;
    }

    /**
     * 上传本地文件到远程服务器
     * @param channelSftp 传递文件的通道
     * @param localFile 本地文件
     * @param remoteFile 远程主机文件
     */
    public static void upload(ChannelSftp channelSftp,String localFile, String remoteFile){
        InputStream inputStream = null;
        try {
            sftpMkdirs(channelSftp,remoteFile);
            inputStream = new FileInputStream(localFile);
            channelSftp.put(inputStream, remoteFile, ChannelSftp.OVERWRITE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * sftp服务器下载文件
     * @param channelSftp
     * @param localFile
     * @param remoteFile
     */
    public static void download(ChannelSftp channelSftp,String localFile, String remoteFile){
        OutputStream outputStream = null;
        try {
            //判断本地路径是否存在
            mkdirs(localFile);
            outputStream = new FileOutputStream(localFile);
            channelSftp.get(remoteFile,outputStream);
        } catch (Exception e) {
            log.error("下载文件失败,{}",e);
        } finally {
            IOUtils.closeQuietly(outputStream);
        }
    }

    /**
     * 本地路径是否存在，不存在则创建
     * @param localFile
     */
    private static void mkdirs(String localFile) {
        String targetPath = localFile.substring(0, localFile.lastIndexOf("/"));
        File directory = new File(targetPath);
        if (!directory.exists()){
            boolean created = directory.mkdirs();
            if (!created){
                log.error("文件目录创建失败:" + targetPath);
            }
        }
    }

    /**
     * 远程主机创建文件目录
     * @param sftpChannel
     * @param remoteFile
     */
    public static void sftpMkdirs(ChannelSftp sftpChannel, String remoteFile) throws SftpException {
        String targetPath = remoteFile.substring(0,remoteFile.lastIndexOf("/"));
        //目录数组
        String[] dirLevels = targetPath.split("/");
        //循环生产目录
        StringBuilder currentPath = new StringBuilder("/");
        for (String dirLevel: dirLevels){
            if (StringUtils.isNotEmpty(dirLevel)){
                currentPath.append(dirLevel).append("/");
                //查看目录是否存在 存在不用创建
                if (!dirExists(sftpChannel,currentPath.toString())){
                    sftpChannel.mkdir(currentPath.toString());
                }
            }
        }
    }

    /**
     * 查看目录是否存在
     * @param channelSftp
     * @param remoteDir
     * @return
     * @throws SftpException
     */
    private static boolean dirExists(ChannelSftp channelSftp, String remoteDir) throws SftpException {
        try {
            channelSftp.ls(remoteDir);
            return true;
        } catch (SftpException e) {
            if (e.getMessage().startsWith("No such file.java")){
                return false;
            } else {
                throw e;
            }
        }
    }




}
